﻿using UnityEditor ;
using UnityEngine ;
using System.IO;


public class AssetBundlePackager
{
    public static void PackTarget(BuildTarget platformTarget, BundleType type)
    {
        Debug.Log("start export:" + type);

        //1创建输出
        CreateOutputFold();

        //2清除之前的Ab名字
        ClearAssetBundlesNameBefore();

        //3 设置Ab名字
        AssetBundleTargetInfo target = AssetBundleConfig.GetTypeTargetInfo(type);
        string fullPath = AssetBundleUtil.AssetPathToFullPath(target.AssetPath);
        ResetAssetBundleName(fullPath, target.NeedCheckDependency);

        //4打包
        AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(AssetBundleConfig.GetOutputPath(),
                BuildAssetBundleOptions.ChunkBasedCompression,
                platformTarget);

        //5显示依赖信息
        ShowManifestInfo(manifest);

        //6 清除AB信息
        AssetDatabase.Refresh();

        ClearAssetBundlesNameBefore();

        Debug.Log("end export:" + type);
    }

    public static  void PackAllTargets(BuildTarget platformTarget)
    {
        Debug.Log("---------------------Assetbundle export begin");

        PackTarget(platformTarget,BundleType.Model);

        Debug.Log("-----------------------Assetbundle export end");
    }

    private static void ResetAssetBundleName(string fullPath , bool checkDependency)
    {
        if (string.IsNullOrEmpty(fullPath))
        {
            return;
        }

        DirectoryInfo folder = new DirectoryInfo(fullPath);
        if (!folder.Exists)
        {
            Debug.LogError("ResetAssetBundleName Error, Path(" + fullPath + ") miss");
            return;
        }

        FileSystemInfo[] files = folder.GetFileSystemInfos();
        foreach (var file in files)
        {
            if (file is DirectoryInfo)
            {
                ResetAssetBundleName(file.FullName, checkDependency);
            }
            else
            {
                if (CheckValid(file.FullName))
                {
                    if (checkDependency)
                    {
                        ResetDependenciesAssetBundleName(file.FullName);
                    }

                    string path = AssetBundleUtil.Normarlize(file.FullName);
                    string projectPath = "Assets" + AssetBundleUtil.FullPathToAssetPath(path);
                    SetAssetBundleName(projectPath);
                }
            }
        }
    }

    private static void ResetDependenciesAssetBundleName(string fullPath)
    {
        if (string.IsNullOrEmpty(fullPath))
        {
            return;
        }

        fullPath = AssetBundleUtil.Normarlize(fullPath);
        string projectPath = "Assets" +  AssetBundleUtil.FullPathToAssetPath(fullPath);

        string[] dependencies = AssetDatabase.GetDependencies(projectPath, false);
        if (dependencies.Length <= 0)
        {
            return;
        }

        for (int i = 0; i < dependencies.Length; ++ i)
        {
            SetAssetBundleName(dependencies[i]);
        }
    }

    //todo  
    private static bool  CheckValid(string fullPath)
    {
        string pathLowCase = fullPath.ToLower();
        if (pathLowCase.EndsWith(".meta")
            || pathLowCase.EndsWith("unity default resources")
            || pathLowCase.EndsWith("unity_builtin_extra")
            || pathLowCase.EndsWith(".cs")
            || pathLowCase.EndsWith(".js")
            || pathLowCase.EndsWith(".fbx")
            || pathLowCase.EndsWith(".mat")
            //|| assetPathLowCase.EndsWith(".shader")
            || pathLowCase.EndsWith(".controller")
            || pathLowCase.EndsWith(".anim")
            )
        {
            return false;
        }
        return true;
    }

    private static void SetAssetBundleName(string projectPath)
    {
        AssetImporter assetImporter = AssetImporter.GetAtPath(projectPath);
        if (null != assetImporter)
        {
            assetImporter.assetBundleName = GetTargetName(projectPath);
        }
    }

    private static string GetTargetName(string projectPath)
    {
        return AssetBundleUtil.GetBundleName(projectPath);
    }

    /// <summary>
    /// 清除之前设置过的AssetBundleName，避免产生不必要的资源也打包
    /// 只要设置了AssetBundleName的，都会进行打包，不论在什么目录下
    /// </summary>
    private static void ClearAssetBundlesNameBefore()
    {
        int length = AssetDatabase.GetAllAssetBundleNames().Length;
        string[] oldAssetBundleNames = new string[length];
        for (int i = 0; i < length; i++)
        {
            oldAssetBundleNames[i] = AssetDatabase.GetAllAssetBundleNames()[i];
        }

        for (int j = 0; j < oldAssetBundleNames.Length; j++)
        {
            AssetDatabase.RemoveAssetBundleName(oldAssetBundleNames[j], true);
        }
    }



    static void CreateOutputFold()
    {
        string output = AssetBundleConfig.GetOutputPath();

        if (Directory.Exists(output))
        {
            Directory.Delete(output, true);
        }

        Directory.CreateDirectory(output);
    }

    static void ShowManifestInfo(AssetBundleManifest manifest)
    {
        string[] allAbs = manifest.GetAllAssetBundles();
        for (int i = 0; i < allAbs.Length; ++i)
        {
            Debug.Log("------AssetBundle Name:" + allAbs[i] + ", Hash:" + manifest.GetAssetBundleHash(allAbs[i]).ToString());
            string[] dependeces = manifest.GetAllDependencies(allAbs[i]);
            for (int di = 0; di < dependeces.Length; ++di)
            {
                Debug.Log(allAbs[i] + " 依赖资源:" + dependeces[di]);
            }
        }

    }
}
